package com.jason.java.lib;

import java.lang.reflect.Field;

/**
 * 一个案例测试所有类型内部类对外部类对象的持有情况
 */
public class LeakDemo {


    /* 持有外部类引用 */
    private IAppListener mAppListener = new IAppListener() {
        private String name;

        @Override
        public void done() {
            System.out.println("匿名内部类对象作为成员变量");
        }
    };
    /* 未持有 */
    private static IAppListener sAppListener = new IAppListener() {
        private String name;

        @Override
        public void done() {
            System.out.println("匿名内部类对象作为static成员变量");
        }
    };

    public static void main(String args[]) {
        LeakDemo leak = new LeakDemo();
        leak.test1();
        leak.test2();
        leak.test3();// test3 《=》test4
        leak.test4();
        leak.test5();
        leak.test6();
    }

    class Dog {
        private String name;
    }

    /* 持有外部类引用 */
    public void test1() {
        Dog dog = new Dog();
        getAllFieldName(dog.getClass());
    }

    static class Cat {
        private String name;
    }

    /* 未持有 */
    private void test2() {
        Cat cat = new Cat();
        getAllFieldName(cat.getClass());
    }

    /* 持有外部类引用 */
    private void test3() {
        class Monkey {
            String name;
        }
        Monkey monkey = new Monkey();
        getAllFieldName(monkey.getClass());
    }

    /* 持有外部类引用 */
    private void test4() {
        // 常用作事件回调的地方(有可能引起内存泄露)
        IAppListener iAppListener = new IAppListener() {
            private String name;

            @Override
            public void done() {
                System.out.println("匿名内部类");
            }
        };
        getAllFieldName(iAppListener.getClass());
    }

    /* 持有外部类引用 */
    private void test5() {
        getAllFieldName(mAppListener.getClass());
    }

    /* 未持有 */
    private void test6() {
        getAllFieldName(sAppListener.getClass());
    }

    private void getAllFieldName(Class<?> clazz) {
        System.out.println("className: ======> " + clazz.getSimpleName());
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());
        }
    }


}
